﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace SharpShare.Storage {
    public class StorageDataStream : Stream {
        private long _position;

        public StorageDataStream(IStorageDataProvider dataProvider, bool ownsStream = true) {
            if (dataProvider == null) {
                throw new ArgumentNullException("dataProvider");
            }

            this.OwnsStream = true;
            this.DataProvider = dataProvider;
        }

        public IStorageDataProvider DataProvider { get; private set; }
        public bool OwnsStream { get; private set; }

        public override bool CanRead {
            get {
                return (this.DataProvider.AccessMode.HasFlag(StorageFileAccess.Read));
            }
        }

        public override bool CanSeek {
            get { return true; }
        }

        public override bool CanWrite {
            get {
                return (this.DataProvider.AccessMode.HasFlag(StorageFileAccess.Write));
            }
        }

        public override void Flush() {
            this.DataProvider.Flush();
        }

        public override long Length {
            get { return this.DataProvider.Length; }
        }

        public override long Position {
            get {
                return _position;
            }
            set {
                _position = value;
            }
        }

        public override int Read(byte[] buffer, int offset, int count) {
            int bytesRead = this.DataProvider.Read(_position, buffer, offset, count);
            _position += bytesRead;
            return bytesRead;
        }

        public override long Seek(long offset, SeekOrigin origin) {
            switch (origin) {
                case SeekOrigin.Begin:
                    _position = offset;
                    break;
                case SeekOrigin.Current:
                    _position += offset;
                    break;
                case SeekOrigin.End:
                    _position = (this.DataProvider.Length - offset);
                    break;
            }

            return _position;
        }

        public override void SetLength(long value) {
            this.DataProvider.SetLength(value);
        }

        public override void Write(byte[] buffer, int offset, int count) {
            this.DataProvider.Write(_position, buffer, offset, count);
            _position += count;
        }

        protected override void Dispose(bool disposing) {
            base.Dispose(disposing);

            if (disposing) {
                if (this.OwnsStream) {
                    this.DataProvider.Close();
                }
            }
        }
    }
}
